/**
 * @file
 */

#ifdef __WIN32
	#include <Windows.h>
#else
	#include <dlfcn.h>
#endif

#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include "mocha/pointers.hpp"
#include "mocha/shared_library.hpp"

using namespace boost::filesystem;

namespace mocha {
shared_library::shared_library(void* lib): lib_(lib) {
	if (!lib_) {}
}
shared_library::~shared_library() {
	close();
}
shared_library_ptr_t shared_library::open(const path& file) {
	void* lib = NULL;
	#ifdef __WIN32
		lib = LoadLibraryA(file.string().c_str());
	#else
		lib = dlopen(file.string().c_str(), RTLD_NOW | RTLD_LOCAL);
	#endif
	if (!lib) {
		std::string error;
		#ifdef __WIN32
			error = "error code " + boost::lexical_cast<std::string>(GetLastError());
		#else
			error = dlerror();
		#endif
		std::cout << "failed to open shared object \"" << file << "\": " << error << "\n";
		return shared_library_ptr_t();
	}
	return shared_library_ptr_t(new shared_library(lib));
}
void* shared_library::symbol(const std::string& name) {
	#ifdef __WIN32
		return GetProcAddress(static_cast<HMODULE>(lib_), name.c_str());
	#else
		return dlsym(lib_, name.c_str());
	#endif
}
void shared_library::close() {
	#ifdef __WIN32
		FreeLibrary(static_cast<HMODULE>(lib_));
	#else
		dlclose(lib_);
	#endif
}
std::string shared_library_from_base_name(const std::string& name) {
	#ifdef __WIN32
		return name + ".dll";
	#else
		return "lib" + name + ".so";
	#endif
}
}

